package com.kwdb.importtool;

import com.kwdb.importtool.ui.MainFrame;
import com.kwdb.importtool.util.ExceptionHandler;
import com.kwdb.importtool.util.LoggerUtil;
import lombok.extern.slf4j.Slf4j;

import javax.swing.*;
import java.awt.*;

/**
 * 应用程序主类
 * 负责应用程序的启动和初始化
 */
@Slf4j
public class Main {

    // 应用程序信息
    public static final String APP_NAME = "MySQL to KWDB migrationTools";
    public static final String VERSION = "1.0.0";
    public static final String BUILD_DATE = "2025-10-15";

    // 系统属性键名
    private static final String PROP_APP_NAME = "kwdb.migration.tool.name";
    private static final String PROP_APP_VERSION = "kwdb.migration.tool.version";
    private static final String PROP_APP_HOME = "kwdb.migration.tool.home";

    /**
     * 应用程序主入口
     */
    public static void main(String[] args) {
        // 设置应用程序属性
        setupApplicationProperties();

        // 解析命令行参数
        CommandLineArgs cliArgs = parseCommandLineArgs(args);

        // 初始化应用程序
        if (!initializeApplication(cliArgs)) {
            System.exit(1);
        }

        // 启动GUI或命令行模式
        if (cliArgs.isGuiMode()) {
            startGuiMode(cliArgs);
        } else {
            startCommandLineMode(cliArgs);
        }
    }

    /**
     * 设置应用程序属性
     */
    private static void setupApplicationProperties() {
        System.setProperty(PROP_APP_NAME, APP_NAME);
        System.setProperty(PROP_APP_VERSION, VERSION);
        System.setProperty(PROP_APP_HOME, getApplicationHome());

        // 设置其他系统属性
        System.setProperty("awt.useSystemAAFontSettings", "on");
        System.setProperty("swing.aatext", "true");
        System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
    }

    /**
     * 获取应用程序主目录
     */
    private static String getApplicationHome() {
        String home = System.getProperty(PROP_APP_HOME);
        if (home == null || home.trim().isEmpty()) {
            home = System.getProperty("user.dir");
        }
        return home;
    }

    /**
     * 解析命令行参数
     */
    private static CommandLineArgs parseCommandLineArgs(String[] args) {
        CommandLineArgs cliArgs = new CommandLineArgs();

        if (args.length == 0) {
            cliArgs.setGuiMode(true);
            return cliArgs;
        }

        for (int i = 0; i < args.length; i++) {
            String arg = args[i];

            switch (arg) {
                case "--gui":
                case "-g":
                    cliArgs.setGuiMode(true);
                    break;

                case "--cli":
                case "-c":
                    cliArgs.setGuiMode(false);
                    break;

                case "--config":
                case "-cfg":
                    if (i + 1 < args.length) {
                        cliArgs.setConfigFile(args[++i]);
                    }
                    break;

                case "--sql-file":
                case "-f":
                    if (i + 1 < args.length) {
                        cliArgs.setSqlFile(args[++i]);
                    }
                    break;

                case "--output-dir":
                case "-o":
                    if (i + 1 < args.length) {
                        cliArgs.setOutputDir(args[++i]);
                    }
                    break;

                case "--kwdb-url":
                    if (i + 1 < args.length) {
                        cliArgs.setKwdbUrl(args[++i]);
                    }
                    break;

                case "--kwdb-user":
                    if (i + 1 < args.length) {
                        cliArgs.setKwdbUser(args[++i]);
                    }
                    break;

                case "--kwdb-password":
                    if (i + 1 < args.length) {
                        cliArgs.setKwdbPassword(args[++i]);
                    }
                    break;

                case "--help":
                case "-h":
                    printHelp();
                    System.exit(0);
                    break;

                case "--version":
                case "-v":
                    printVersion();
                    System.exit(0);
                    break;

                case "--verbose":
                case "-V":
                    cliArgs.setVerbose(true);
                    break;

                case "--skip-errors":
                    cliArgs.setSkipErrors(true);
                    break;

                case "--validate":
                    cliArgs.setValidate(true);
                    break;

                default:
                    // 如果参数不是以-开头，可能是SQL文件路径
                    if (!arg.startsWith("-") && cliArgs.getSqlFile() == null) {
                        cliArgs.setSqlFile(arg);
                    } else {
                        System.err.println("未知参数: " + arg);
                        printHelp();
                        System.exit(1);
                    }
                    break;
            }
        }
        cliArgs.setOriginalArgs(args);
        return cliArgs;
    }

    /**
     * 初始化应用程序
     */
    private static boolean initializeApplication(CommandLineArgs cliArgs) {
        try {
            // 设置异常处理器
            ExceptionHandler.setupGlobalExceptionHandler();

            // 初始化日志系统
            initializeLogging(cliArgs);

            // 记录启动信息
            logApplicationStart(cliArgs);

            // 检查系统要求
            if (!checkSystemRequirements()) {
                return false;
            }

            log.info("The application initialization is complete");
            return true;

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 初始化日志系统
     */
    private static void initializeLogging(CommandLineArgs cliArgs) {
        try {
            if (cliArgs.getConfigFile() != null) {
                LoggerUtil.initializeLogging(cliArgs.getConfigFile());
            } else {
                LoggerUtil.initializeLogging();
            }

            // 设置详细模式
            if (cliArgs.isVerbose()) {
                // 这里可以设置更详细的日志级别
                System.setProperty("log4j2.level", "DEBUG");
            }

        } catch (Exception e) {
            System.err.println("日志系统初始化失败，使用默认配置: " + e.getMessage());
            LoggerUtil.setupFallbackLogging();
        }
    }

    /**
     * 记录应用程序启动信息
     */
    private static void logApplicationStart(CommandLineArgs cliArgs) {
        log.info("=== {} v{} ===", APP_NAME, VERSION);
        log.info("构建日期: {}", BUILD_DATE);
        log.info("Java版本: {}", System.getProperty("java.version"));
        log.info("操作系统: {} {}", System.getProperty("os.name"), System.getProperty("os.version"));
        log.info("工作目录: {}", System.getProperty("user.dir"));
        log.info("应用程序模式: {}", cliArgs.isGuiMode() ? "图形界面" : "命令行");

        if (cliArgs.getSqlFile() != null) {
            log.info("SQL文件: {}", cliArgs.getSqlFile());
        }

        if (log.isDebugEnabled()) {
            log.debug("命令行参数: {}", String.join(" ", java.util.Arrays.asList(cliArgs.getOriginalArgs())));
            log.debug("系统属性: {}", System.getProperties());
        }
    }

    /**
     * 检查系统要求
     */
    private static boolean checkSystemRequirements() {
        // 检查Java版本
        String javaVersion = System.getProperty("java.version");
        if (!isJavaVersionSupported(javaVersion)) {
            String errorMsg = String.format(
                    "不支持的Java版本: %s。需要Java 1.8或更高版本。",
                    javaVersion
            );
            showError(errorMsg);
            return false;
        }

        // 检查操作系统
        String osName = System.getProperty("os.name").toLowerCase();
        if (!isOperatingSystemSupported(osName)) {
            log.warn("操作系统 {} 可能不完全支持", osName);
        }

        // 检查内存
        long maxMemory = Runtime.getRuntime().maxMemory() / (1024 * 1024); // MB
        if (maxMemory < 512) {
            log.warn("可用内存较低 ({}MB)，建议至少512MB", maxMemory);
        }

        return true;
    }

    /**
     * 检查Java版本是否支持
     */
    private static boolean isJavaVersionSupported(String javaVersion) {
        try {
            // 检查是否为Java 1.8或更高版本
            if (javaVersion.startsWith("1.8")) {
                return true;
            }

            // 对于Java 9+，版本格式为 "9", "10", "11" 等
            int majorVersion = getJavaMajorVersion(javaVersion);
            return majorVersion >= 8;

        } catch (Exception e) {
            log.warn("无法解析Java版本: {}", javaVersion, e);
            return true; // 如果无法解析，假设支持
        }
    }

    /**
     * 获取Java主版本号
     */
    private static int getJavaMajorVersion(String javaVersion) {
        if (javaVersion.startsWith("1.")) {
            // Java 8及更早版本: "1.8.0_291"
            return Integer.parseInt(javaVersion.substring(2, 3));
        } else {
            // Java 9及更新版本: "9.0.1", "11.0.2"
            String[] parts = javaVersion.split("\\.");
            return Integer.parseInt(parts[0]);
        }
    }

    /**
     * 检查操作系统是否支持
     */
    private static boolean isOperatingSystemSupported(String osName) {
        return osName.contains("windows") ||
                osName.contains("linux") ||
                osName.contains("mac");
    }

    /**
     * 启动图形界面模式
     */
    private static void startGuiMode(CommandLineArgs cliArgs) {
        log.info("启动图形界面模式");

        try {
            // 设置系统外观
            setSystemLookAndFeel();

            // 创建并显示主窗口
            SwingUtilities.invokeAndWait(() -> {
                MainFrame mainFrame = new MainFrame();
                centerFrameOnScreen(mainFrame);
                mainFrame.setVisible(true);

                // 如果有命令行参数，传递给主窗口
                applyCommandLineArgsToGui(mainFrame, cliArgs);
            });

        } catch (Exception e) {
            log.error("启动图形界面失败", e);
            showError("无法启动图形界面: " + e.getMessage());
            System.exit(1);
        }
    }

    /**
     * 设置系统外观
     */
    private static void setSystemLookAndFeel() {
        try {
            //暂定
//            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeel());
            // 1. 获取系统默认外观的类名（此方法无异常）
            String systemLafClassName = UIManager.getSystemLookAndFeelClassName();
            // 2. 应用系统外观（此方法会抛出受检异常，必须捕获）
            UIManager.setLookAndFeel(systemLafClassName);

            // 设置一些UI属性以改善外观
            UIManager.put("TabbedPane.tabInsets", new javax.swing.plaf.InsetsUIResource(6, 8, 6, 8));
            UIManager.put("TabbedPane.selectedLabelShift", 0);
            UIManager.put("TabbedPane.labelShift", 0);

        } catch (Exception e) {
            log.warn("无法设置系统外观: {}", e.getMessage());
        }
    }

    /**
     * 将窗口居中显示
     */
    private static void centerFrameOnScreen(Window window) {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension windowSize = window.getSize();

        int x = (screenSize.width - windowSize.width) / 2;
        int y = (screenSize.height - windowSize.height) / 2;

        window.setLocation(x, y);
    }

    /**
     * 将命令行参数应用到GUI
     */
    private static void applyCommandLineArgsToGui(MainFrame mainFrame, CommandLineArgs cliArgs) {
        // 这里可以实现将命令行参数传递给主窗口的逻辑
        // 例如：自动加载指定的SQL文件或配置

        if (cliArgs.getSqlFile() != null) {
            log.info("从命令行加载SQL文件: {}", cliArgs.getSqlFile());
            // mainFrame.loadSqlFile(cliArgs.getSqlFile());
        }

        if (cliArgs.getConfigFile() != null) {
            log.info("从命令行加载配置文件: {}", cliArgs.getConfigFile());
            // mainFrame.loadConfigFile(cliArgs.getConfigFile());
        }
    }

    /**
     * 启动命令行模式
     */
    private static void startCommandLineMode(CommandLineArgs cliArgs) {
        log.info("启动命令行模式");

        try {
            // 验证必要的参数
            if (!validateCommandLineArgs(cliArgs)) {
                System.exit(1);
            }

            // 执行迁移任务
            performCommandLineMigration(cliArgs);

        } catch (Exception e) {
            log.error("命令行模式执行失败", e);
            System.exit(1);
        }
    }

    /**
     * 验证命令行参数
     */
    private static boolean validateCommandLineArgs(CommandLineArgs cliArgs) {
        if (cliArgs.getSqlFile() == null) {
            System.err.println("错误: 必须指定SQL文件路径");
            printHelp();
            return false;
        }

        if (cliArgs.getKwdbUrl() == null) {
            System.err.println("错误: 必须指定KWDB连接URL");
            printHelp();
            return false;
        }

        if (cliArgs.getKwdbUser() == null) {
            System.err.println("错误: 必须指定KWDB用户名");
            printHelp();
            return false;
        }

        // 检查SQL文件是否存在
        if (!new java.io.File(cliArgs.getSqlFile()).exists()) {
            System.err.println("错误: SQL文件不存在: " + cliArgs.getSqlFile());
            return false;
        }

        return true;
    }

    /**
     * 执行命令行迁移任务
     */
    private static void performCommandLineMigration(CommandLineArgs cliArgs) {
        log.info("开始命令行迁移任务");

        try {
            // 这里实现命令行迁移逻辑
            // 创建配置对象
            // 执行迁移过程
            // 输出结果

            log.info("命令行迁移任务完成");

        } catch (Exception e) {
            log.error("命令行迁移任务失败", e);
            throw new RuntimeException("迁移任务失败", e);
        }
    }

    /**
     * 显示错误消息
     */
    private static void showError(String message) {
        if (GraphicsEnvironment.isHeadless()) {
            System.err.println("错误: " + message);
        } else {
            JOptionPane.showMessageDialog(null, message, "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * 打印帮助信息
     */
    private static void printHelp() {
        System.out.println(APP_NAME + " v" + VERSION);
        System.out.println();
        System.out.println("用法: java -jar kwdb-import-tool.jar [选项] [SQL文件]");
        System.out.println();
        System.out.println("选项:");
        System.out.println("  -g, --gui                   启动图形界面模式（默认）");
        System.out.println("  -c, --cli                  启动命令行模式");
        System.out.println("  -f, --sql-file <文件>      指定SQL文件路径");
        System.out.println("  -cfg, --config <文件>      指定配置文件路径");
        System.out.println("  -o, --output-dir <目录>    指定输出目录");
        System.out.println("      --kwdb-url <URL>       指定KWDB连接URL");
        System.out.println("      --kwdb-user <用户名>   指定KWDB用户名");
        System.out.println("      --kwdb-password <密码> 指定KWDB密码");
        System.out.println("      --skip-errors          跳过错误继续执行");
//        System.out.println("      --validate             迁移后验证数据");
        System.out.println("  -V, --verbose              详细输出模式");
        System.out.println("  -v, --version              显示版本信息");
        System.out.println("  -h, --help                 显示此帮助信息");
        System.out.println();
        System.out.println("示例:");
        System.out.println("  # 图形界面模式");
        System.out.println("  java -jar kwdb-import-tool.jar");
        System.out.println();
        System.out.println("  # 命令行模式");
        System.out.println("  java -jar kwdb-import-tool.jar --cli --sql-file dump.sql \\");
        System.out.println("      --kwdb-url jdbc:kaiwudb://localhost:8123/default \\");
        System.out.println("      --kwdb-user admin --kwdb-password admin");
        System.out.println();
        System.out.println("  # 使用配置文件");
        System.out.println("  java -jar kwdb-import-tool.jar -cfg config.properties -f dump.sql");
    }

    /**
     * 打印版本信息
     */
    private static void printVersion() {
        System.out.println(APP_NAME + " v" + VERSION);
        System.out.println("构建日期: " + BUILD_DATE);
        System.out.println("Java版本: " + System.getProperty("java.version"));
        System.out.println("操作系统: " + System.getProperty("os.name") + " " + System.getProperty("os.version"));
    }

    /**
     * 命令行参数类
     */
    private static class CommandLineArgs {
        private boolean guiMode = true;
        private String configFile;
        private String sqlFile;
        private String outputDir;
        private String kwdbUrl;
        private String kwdbUser;
        private String kwdbPassword;
        private boolean verbose = false;
        private boolean skipErrors = false;
        private boolean validate = true;
        private String[] originalArgs;

        // Getters and Setters
        public boolean isGuiMode() { return guiMode; }
        public void setGuiMode(boolean guiMode) { this.guiMode = guiMode; }

        public String getConfigFile() { return configFile; }
        public void setConfigFile(String configFile) { this.configFile = configFile; }

        public String getSqlFile() { return sqlFile; }
        public void setSqlFile(String sqlFile) { this.sqlFile = sqlFile; }

        public String getOutputDir() { return outputDir; }
        public void setOutputDir(String outputDir) { this.outputDir = outputDir; }

        public String getKwdbUrl() { return kwdbUrl; }
        public void setKwdbUrl(String kwdbUrl) { this.kwdbUrl = kwdbUrl; }

        public String getKwdbUser() { return kwdbUser; }
        public void setKwdbUser(String kwdbUser) { this.kwdbUser = kwdbUser; }

        public String getKwdbPassword() { return kwdbPassword; }
        public void setKwdbPassword(String kwdbPassword) { this.kwdbPassword = kwdbPassword; }

        public boolean isVerbose() { return verbose; }
        public void setVerbose(boolean verbose) { this.verbose = verbose; }

        public boolean isSkipErrors() { return skipErrors; }
        public void setSkipErrors(boolean skipErrors) { this.skipErrors = skipErrors; }

        public boolean isValidate() { return validate; }
        public void setValidate(boolean validate) { this.validate = validate; }

        public String[] getOriginalArgs() { return originalArgs; }
        public void setOriginalArgs(String[] originalArgs) { this.originalArgs = originalArgs; }
    }
}